﻿using LxBasic;
using System;
using System.Diagnostics;
using System.Security.Cryptography;

namespace LxCore
{
    public class FindError
    {
        public static void FindMaxAndMin(double[] array)
        {
            double max = array[0];
            double min = array[0];
            int maxIndex = 0;
            int minIndex = 0;
            for (int i1 = 1; i1 < array.Length; i1++)
            {
                if (array[i1] > max)
                {
                    max = array[i1];
                    maxIndex = i1;
                }
                else if (array[i1] < min)
                {
                    min = array[i1];
                    minIndex = i1;
                }
            }
            Debug.WriteLine("max:{0} at {1}; min:{2} at {3}", max, maxIndex, min, minIndex);
        }
        public static int FindNearCell(FvZone z, Vector3d pos)
        {
            var inncells = z.InnCells;
            double len = double.MaxValue;
            int cell = 0;
            for (int i1 = 0; i1 < inncells.Length; i1++)
            {
                double l = (inncells[i1].Center - pos).LengthSquared();
                if (l < len)
                {
                    cell = i1;
                    len = l;
                }
            }
            return cell;
        }
        public static void PrintGrad(ScalarBase s,int innCellId)
        {

        }
        public static void PrintAxb(object obj, int cellindex)
        {
            Debug.WriteLine("Cell Index {0}", cellindex);
            if (obj is ScalarBase sx)
            {
                Debug.WriteLine("x= {0} ,gradx= {1} ", sx.InnX[cellindex], sx.Grad[cellindex]);
            }
            if (obj is MatrixBase mat)
            {
                double alux = 0;
                Debug.WriteLine("A_Diag= {0} ,b= {1} ", mat.ADiag[cellindex], mat.B[cellindex]);
                FvInnCell[] cells = mat.Zone.InnCells;
                FvInnFace[] innFaces = mat.Zone.InnFaces;
                FvBouFace[] bouFaces = mat.Zone.BouFaces;
                ref FvInnCell cell = ref cells[cellindex];
                int i1 = 0;
                for (; i1 < cell.InnOFaceEnd; i1++)
                {
                    int fid = cell.AdjFaces[i1];
                    int cid = innFaces[fid].NSideCell;
                    Debug.WriteLine($"IOface Id= {fid},InnCell Id={cid} ,ALUO= {mat.AInnO[fid]} xN= {mat.InnX[cid]} ");
                    alux += mat.AInnO[fid] * mat.InnX[innFaces[fid].NSideCell];
                }
                for (; i1 < cell.InnNFaceEnd; i1++)
                {
                    int fid = cell.AdjFaces[i1];
                    int cid = innFaces[fid].OSideCell;
                    Debug.WriteLine($"INface Id= {fid} ,InnCell Id={cid},ALUN= {mat.AInnN[fid]} xO= {mat.InnX[cid]} " );
                    alux += mat.AInnN[fid] * mat.InnX[innFaces[fid].OSideCell];
                }
                for (; i1 < cell.AdjFaces.Length; i1++)
                {
                    int fid = cell.AdjFaces[i1];
                    Debug.WriteLine("Bouface Id= {0} ,BouAH= {1} xb={2}", fid, mat.ABouH[fid], mat.BouX[fid]);
                    alux += mat.ABouH[fid];
                }
                Debug.WriteLine("cal x = {0} ", (mat.B[cellindex]-alux)/ mat.ADiag[cellindex]);
            }
            //if (obj is EquationWithTransTerm flow)
            //{
            //    FvCell[] cells = flow.Zone.Cells;
            //    FvFace[] faces = flow.Zone.Faces;
            //    foreach (var face in cells[cellindex].OFaces)
            //    {
            //        Console.WriteLine("Oface Id= {0} ,ALUO= {1} xN= {2} ", face, flow.ALUO[face], flow.XInn[faces[face].NSideCell]);
            //    }
            //    foreach (var face in flow.Zone.Cells[cellindex].NFaces)
            //    {
            //        Console.WriteLine("Nface Id= {0} ,ALUN= {1} xO= {2} ", face, flow.ALUN[face], flow.XInn[faces[face].OSideCell]);
            //    }
            //}
            //else if (obj is ScalarBase_ALUDiff aludiff)
            //{
            //    Console.WriteLine("A_LU_Diff:");
            //    foreach (var face in aludiff.zone.cells[cellindex].CellFacesAsO)
            //    {
            //        Console.WriteLine("Oface Id= {0},ALU={1}", face, aludiff.A_LU_Diff[face]);
            //    }
            //    foreach (var face in aludiff.zone.cells[cellindex].CellFacesAsN)
            //    {
            //        Console.WriteLine("Nface Id= {0},ALU={1}", face, aludiff.A_LU_Diff[face]);
            //    }
            //}
        }
        //public static void PrintAxb_x2common(object obj, int cellindex)
        //{
        //    Console.WriteLine("Cell Index {0}", cellindex);
        //    if (obj is ScalarBase sx)
        //    {
        //        if (cellindex < sx.Grad.Length)
        //        {
        //            Console.WriteLine("x2common,x= {0} ", sx.XInn[cellindex]);
        //            Console.WriteLine("x= {0} ,gradx= {1} ", sx.XShare[cellindex], sx.Grad[cellindex]);
        //        }
        //        else
        //        {
        //            Console.WriteLine("x= {0} ", sx.XInn[cellindex]);
        //        }
        //    }
        //    if (obj is MatrixADbBase sab)
        //    {
        //        Console.WriteLine("A_Diag= {0} ,b= {1} ", sab.ADiag[cellindex], sab.B[cellindex]);
        //    }
        //    if (obj is EquationWithTransTerm flow)
        //    {
        //        FvCell[] cells = flow.Zone.Cells;
        //        FvFace[] faces = flow.Zone.Faces;
        //        foreach (var face in cells[cellindex].OFaces)
        //        {
        //            Console.WriteLine("Oface Id= {0} ,ALUO= {1} xN= {2} ", face, flow.ALUO[face], flow.XInn[faces[face].NSideCell]);
        //        }
        //        foreach (var face in flow.Zone.Cells[cellindex].NFaces)
        //        {
        //            Console.WriteLine("Nface Id= {0} ,ALUN= {1} xO= {2} ", face, flow.ALUN[face], flow.XInn[faces[face].OSideCell]);
        //        }
        //    }
        //    //else if (obj is ScalarBase_ALUDiff aludiff)
        //    //{
        //    //    Console.WriteLine("A_LU_Diff:");
        //    //    foreach (var face in aludiff.zone.cells[cellindex].CellFacesAsO)
        //    //    {
        //    //        Console.WriteLine("Oface Id= {0},ALU={1}", face, aludiff.A_LU_Diff[face]);
        //    //    }
        //    //    foreach (var face in aludiff.zone.cells[cellindex].CellFacesAsN)
        //    //    {
        //    //        Console.WriteLine("Nface Id= {0},ALU={1}", face, aludiff.A_LU_Diff[face]);
        //    //    }
        //    //}
        //}
        //public static void PrintAxb_common2x(object obj, int cellindex)
        //{
        //    Console.WriteLine("Cell Index {0}", cellindex);
        //    if (obj is ScalarBase sx)
        //    {
        //        if (cellindex < sx.Grad.Length)
        //        {
        //            Console.WriteLine("common2x,x_common= {0} ", sx.XShare[cellindex]);
        //            Console.WriteLine("x= {0} ,gradx= {1} ", sx.XInn[cellindex], sx.Grad[cellindex]);
        //        }
        //        else
        //        {
        //            Console.WriteLine("x= {0} ", sx.XInn[cellindex]);
        //        }
        //    }
        //    if (obj is MatrixADbBase sab)
        //    {
        //        Console.WriteLine("A_Diag= {0} ,b= {1} ", sab.ADiag[cellindex], sab.B[cellindex]);
        //    }
        //    if (obj is EquationWithTransTerm flow)
        //    {
        //        FvCell[] cells = flow.Zone.Cells;
        //        FvFace[] faces = flow.Zone.Faces;
        //        foreach (var face in cells[cellindex].OFaces)
        //        {
        //            Console.WriteLine("Oface Id= {0} ,ALUO= {1} xN= {2} ", face, flow.ALUO[face], flow.XShare[faces[face].NSideCell]);
        //        }
        //        foreach (var face in flow.Zone.Cells[cellindex].NFaces)
        //        {
        //            Console.WriteLine("Nface Id= {0} ,ALUN= {1} xO= {2} ", face, flow.ALUN[face], flow.XShare[faces[face].OSideCell]);
        //        }
        //    }
        //    //else if (obj is ScalarBase_ALUDiff aludiff)
        //    //{
        //    //    Console.WriteLine("A_LU_Diff:");
        //    //    foreach (var face in aludiff.zone.cells[cellindex].CellFacesAsO)
        //    //    {
        //    //        Console.WriteLine("Oface Id= {0},ALU={1}", face, aludiff.A_LU_Diff[face]);
        //    //    }
        //    //    foreach (var face in aludiff.zone.cells[cellindex].CellFacesAsN)
        //    //    {
        //    //        Console.WriteLine("Nface Id= {0},ALU={1}", face, aludiff.A_LU_Diff[face]);
        //    //    }
        //    //}
        //}
        public static void FindNAN(double[] target)
        {
            for (int i1 = 0; i1 < target.Length; i1++)
            {
                if (double.IsNaN(target[i1])) throw new Exception("NAN");
            }
        }
        public static bool FindNaN(double[] target)
        {
            for (int i1 = 0; i1 < target.Length; i1++)
            {
                if (double.IsNaN(target[i1])) return true;
            }
            return false;
        }
        public static bool FindUnnormal(double[] target)
        {
            for (int i1 = 0; i1 < target.Length; i1++)
            {
                if (double.IsNaN(target[i1]) || double.IsInfinity(target[i1]) || double.IsNegativeInfinity(target[i1])) return true;
            }
            return false;
        }


    }
}
